package com.cheng.example.book.advise151.chap1.client17;

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;


/**
 * 建议17：慎用动态编译
 *
 * 静态编译已经能够帮我们处理大部分的工作，甚至是全部的工作，
 * 即使真的需要动态编译，也有很好的替代方案，比如Jruby、Groovy等无缝的脚本语言。另外，我们在使用动态编译时，需要注意以下几点
 */
public class Client17 {
    public static void main(String[] args) throws Exception {
        // Java源代码
        String sourceStr = "public class Hello { public String sayHello (String name) {return \"Hello,\"+name+\"!\";}}";
        // 类名及文件名
        String clsName = "Hello";
        // 方法名
        String methodName = "sayHello";
        // 当前编译器
        JavaCompiler cmp = ToolProvider.getSystemJavaCompiler();
        // Java标准文件管理器
        StandardJavaFileManager fm = cmp.getStandardFileManager(null, null,
                null);
        // Java文件对象
        JavaFileObject jfo = new StringJavaObject(clsName, sourceStr);
        // 编译参数，类似于javac <options>中的options
        List<String> optionsList = new ArrayList<String>();
        // 编译文件的存放地方，注意：此处是为Eclipse工具特设的
        optionsList.addAll(Arrays.asList("-d", "/target"));
        // 要编译的单元
        List<JavaFileObject> jfos = Arrays.asList(jfo);
        // 设置编译环境
        JavaCompiler.CompilationTask task = cmp.getTask(null, fm, null,
                optionsList, null, jfos);
        // 编译成功
        if (task.call()) {
            // 生成对象
            Object obj = Class.forName(clsName).newInstance();
            Class<? extends Object> cls = obj.getClass();
            // 调用sayHello方法
            Method m = cls.getMethod(methodName, String.class);
            String str = (String) m.invoke(obj, "Dynamic Compilation");
            System.out.println(str);
        }

    }
}
